package com.xiaoshuidi.cloud.module.member.service.feedback;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xiaoshuidi.cloud.framework.common.exception.ServiceException;
import com.xiaoshuidi.cloud.framework.common.exception.enums.GlobalErrorCodeConstants;
import com.xiaoshuidi.cloud.framework.common.pojo.PageResult;
import com.xiaoshuidi.cloud.module.contract.api.ContractApi;
import com.xiaoshuidi.cloud.module.contract.vo.ContractRoomReqVO;
import com.xiaoshuidi.cloud.module.member.controller.admin.feedback.vo.*;
import com.xiaoshuidi.cloud.module.member.controller.app.feedback.vo.HistoricalFeedbackReqVO;
import com.xiaoshuidi.cloud.module.member.controller.app.feedback.vo.HistoricalFeedbackRespVO;
import com.xiaoshuidi.cloud.module.member.controller.app.feedback.vo.MemberFeedbackCreateReqVO;
import com.xiaoshuidi.cloud.module.member.convert.feedback.MemberFeedbackConvert;
import com.xiaoshuidi.cloud.module.member.enums.FeedbackStatusEnum;
import com.xiaoshuidi.cloud.module.member.pojo.feedback.MemberFeedback;
import com.xiaoshuidi.cloud.module.member.mapper.feedback.MemberFeedbackMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaoshuidi.cloud.module.rooms.api.apartment.ApartmentApi;
import com.xiaoshuidi.cloud.module.rooms.api.apartment.dto.ApartmentListDto;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

import static com.xiaoshuidi.cloud.module.member.enums.ErrorCodeConstants.FEEDBACK_EXIST_ERROR;

/**
 * <p>
 * 意见反馈 服务实现类
 * </p>
 *
 * @author hans.zhang
 * @since 2023-11-28
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class MemberFeedbackServiceImpl extends ServiceImpl<MemberFeedbackMapper, MemberFeedback> implements MemberFeedbackService {

    private final MemberFeedbackMapper memberFeedbackMapper;
    private final ContractApi contractApi;
    private final ApartmentApi apartmentApi;

    /**
     * 创建意见反馈
     *
     * @param loginUserId 登录用户ID
     * @param createReqVO 创建参数
     * @return 意见反馈ID
     */
    @Override
    public Long create(Long loginUserId, MemberFeedbackCreateReqVO createReqVO) {

        MemberFeedback memberFeedback = new MemberFeedback();
        BeanUtil.copyProperties(createReqVO, memberFeedback);

        if (ObjectUtil.isNotEmpty(createReqVO.getFeedbackImages())) {
            if (createReqVO.getFeedbackImages().size() > 10) {
                throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), "反馈图片限制10张!");
            }
            memberFeedback.setFeedbackImage(String.join(";", createReqVO.getFeedbackImages()));
        }

        // 租客最新合同的所属门店
        List<ContractRoomReqVO> contractRoomReqVOS = contractApi.getRoomIdByUserId(loginUserId).getCheckedData();
        if (ObjectUtil.isNotEmpty(contractRoomReqVOS)) {
            // 最新的合同
            ContractRoomReqVO contractRoomReqVO = contractRoomReqVOS.get(0);
            Long apartmentId = contractRoomReqVO.getApartmentId();
            ApartmentListDto apartmentListDto = apartmentApi.getById(apartmentId).getCheckedData();
            if (ObjectUtil.isEmpty(apartmentListDto)) {
                throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), "门店不存在!");
            }
            memberFeedback.setDeptId(apartmentListDto.getDeptId());
            memberFeedback.setApartmentId(apartmentId);
            memberFeedback.setApartmentName(apartmentListDto.getName());
        }
        memberFeedback.setStatus(FeedbackStatusEnum.UNPROCESSED.getCode());
        memberFeedbackMapper.insert(memberFeedback);
        return memberFeedback.getId();
    }

    /**
     * 分页查询
     *
     * @param pageReqVO
     * @return
     */
    @Override
    public PageResult<MemberFeedbackPageRespVO> feedbackPage(MemberFeedbackPageReqVO pageReqVO) {
        LambdaQueryWrapper<MemberFeedback> wrapper = Wrappers.lambdaQuery();
        if (ObjectUtil.isAllNotEmpty(pageReqVO.getCreateTimeEnd(), pageReqVO.getCreateTimeStart())) {
            wrapper.between(MemberFeedback::getCreateTime, pageReqVO.getCreateTimeStart(), pageReqVO.getCreateTimeEnd());
        }
        if (ObjectUtil.isAllNotEmpty(pageReqVO.getProcessingTimeStart(), pageReqVO.getProcessingTimeEnd())) {
            wrapper.between(MemberFeedback::getProcessingTime, pageReqVO.getProcessingTimeStart(), pageReqVO.getProcessingTimeEnd());
        }
        wrapper.eq(ObjectUtil.isNotEmpty(pageReqVO.getStatus()), MemberFeedback::getStatus, pageReqVO.getStatus());
        wrapper.eq(ObjectUtil.isNotEmpty(pageReqVO.getProcessorUserId()), MemberFeedback::getProcessorUserId, pageReqVO.getProcessorUserId());
        if(ObjectUtil.isNotEmpty(pageReqVO.getApartmentId()) && pageReqVO.getApartmentId().equals(0L)){
            wrapper.isNull(MemberFeedback::getApartmentId);
        } else if (ObjectUtil.isNotEmpty(pageReqVO.getApartmentId())) {
            wrapper.eq(MemberFeedback::getApartmentId, pageReqVO.getApartmentId());
        }
        wrapper.and(ObjectUtil.isNotEmpty(pageReqVO.getSearchBox()), w -> {
            w.like(MemberFeedback::getUserName, "%" + pageReqVO.getSearchBox() + "%")
                    .or()
                    .like(MemberFeedback::getMobile, "%" + pageReqVO.getSearchBox() + "%")
                    .or()
                    .like(MemberFeedback::getFeedback, "%" + pageReqVO.getSearchBox() + "%");
        });
        wrapper.orderByAsc(MemberFeedback::getStatus);
        wrapper.orderByDesc(MemberFeedback::getCreateTime);
        Page<MemberFeedback> page = memberFeedbackMapper.selectPage(new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize()), wrapper);
        List<MemberFeedbackPageRespVO> respVOS = MemberFeedbackConvert.INSTANCE.convertList(page.getRecords());
        return new PageResult<>(respVOS, page.getTotal());
    }

    /**
     * 查看
     * @param feedbackId
     * @return
     */
    @Override
    public MemberFeedbackGetRespVO get(Long feedbackId) {
        MemberFeedback memberFeedback = memberFeedbackMapper.selectById(feedbackId);
        MemberFeedbackGetRespVO respVO = MemberFeedbackConvert.INSTANCE.convert(memberFeedback);
        if(ObjectUtil.isNotEmpty(memberFeedback.getFeedbackImage())){
            respVO.setFeedbackImages(CollectionUtil.toList(memberFeedback.getFeedbackImage().split(";")));
        }
        if(ObjectUtil.isNotEmpty(memberFeedback.getProcessingImage())){
            respVO.setProcessingImages(CollectionUtil.toList(memberFeedback.getProcessingImage().split(";")));
        }
        return respVO;
    }

    /**
     * 处理
     * @param handleReqVO
     * @return
     */
    @Override
    public Boolean handle(MemberFeedbackHandleReqVO handleReqVO) {
        MemberFeedback memberFeedback = this.checkAndGet(handleReqVO.getFeedbackId());
        memberFeedback.setProcessingTime(handleReqVO.getProcessingTime());
        memberFeedback.setProcessor(handleReqVO.getProcessor());
        memberFeedback.setProcessorUserId(handleReqVO.getProcessorUserId());
        memberFeedback.setProcessingProgram(handleReqVO.getProcessingProgram());
        if (ObjectUtil.isNotEmpty(handleReqVO.getProcessingImages())) {
            if (handleReqVO.getProcessingImages().size() > 10) {
                throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), "图片限制10张!");
            }
            memberFeedback.setProcessingImage(String.join(";", handleReqVO.getProcessingImages()));
        }
        memberFeedback.setStatus(FeedbackStatusEnum.PROCESSED.getCode());
        memberFeedbackMapper.updateById(memberFeedback);
        return Boolean.TRUE;
    }

    /**
     * 分配门店
     * @param assignApartmentReqVO
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean assignApartment(AssignApartmentReqVO assignApartmentReqVO) {
        ApartmentListDto apartmentListDto = apartmentApi.getById(assignApartmentReqVO.getApartmentId()).getCheckedData();
        if (ObjectUtil.isEmpty(apartmentListDto)) {
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), "门店不存在!");
        }
        LambdaQueryWrapper<MemberFeedback> wrapper = Wrappers.lambdaQuery();
        wrapper.in(MemberFeedback::getId, assignApartmentReqVO.getFeedbackIds());
        List<MemberFeedback> memberFeedbacks = memberFeedbackMapper.selectList(wrapper);
        memberFeedbacks.forEach( memberFeedback -> {
            memberFeedback.setApartmentId(apartmentListDto.getId());
            memberFeedback.setApartmentName(apartmentListDto.getName());
            memberFeedback.setDeptId(apartmentListDto.getDeptId());
        });
        this.updateBatchById(memberFeedbacks);
        return Boolean.TRUE;
    }

    /**
     * 历史反馈
     *
     * @param loginUserId
     * @param historicalFeedbackReqVO
     * @return
     */
    @Override
    public PageResult<HistoricalFeedbackRespVO> historicalFeedback(Long loginUserId, HistoricalFeedbackReqVO historicalFeedbackReqVO) {
        LambdaQueryWrapper<MemberFeedback> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(MemberFeedback::getCreator, loginUserId);
        wrapper.orderByDesc(MemberFeedback::getCreateTime);
        Page<MemberFeedback> page = memberFeedbackMapper.selectPage(new Page<>(historicalFeedbackReqVO.getPageNo(), historicalFeedbackReqVO.getPageSize()), wrapper);
        List<HistoricalFeedbackRespVO> respVOS = new ArrayList<>();
        page.getRecords().forEach(record -> {
            HistoricalFeedbackRespVO respVO = new HistoricalFeedbackRespVO();
            if(ObjectUtil.isNotEmpty(record.getFeedbackImage())){
                respVO.setFeedbackImage(CollectionUtil.toList(record.getFeedbackImage().split(";")));
            }
            if(ObjectUtil.isNotEmpty(record.getProcessingImage())){
                respVO.setProcessingImage(CollectionUtil.toList(record.getProcessingImage().split(";")));
            }
            respVO.setFeedback(record.getFeedback());
            respVO.setCreateTime(record.getCreateTime());
            respVO.setProcessingTime(record.getProcessingTime());
            respVO.setProcessingProgram(record.getProcessingProgram());
            respVOS.add(respVO);
        });
        return new PageResult<>(respVOS, page.getTotal());
    }

    /**
     * 导出查询
     * @param pageReqVO
     * @return
     */
    @Override
    public List<MemberFeedbackPageRespVO> exportList(MemberFeedbackPageReqVO pageReqVO) {
        LambdaQueryWrapper<MemberFeedback> wrapper = Wrappers.lambdaQuery();
        if (ObjectUtil.isAllNotEmpty(pageReqVO.getCreateTimeEnd(), pageReqVO.getCreateTimeStart())) {
            wrapper.between(MemberFeedback::getCreateTime, pageReqVO.getCreateTimeStart(), pageReqVO.getCreateTimeEnd());
        }
        if (ObjectUtil.isAllNotEmpty(pageReqVO.getProcessingTimeStart(), pageReqVO.getProcessingTimeEnd())) {
            wrapper.between(MemberFeedback::getProcessingTime, pageReqVO.getProcessingTimeStart(), pageReqVO.getProcessingTimeEnd());
        }
        wrapper.eq(ObjectUtil.isNotEmpty(pageReqVO.getStatus()), MemberFeedback::getStatus, pageReqVO.getStatus());
        wrapper.eq(ObjectUtil.isNotEmpty(pageReqVO.getProcessorUserId()), MemberFeedback::getProcessorUserId, pageReqVO.getProcessorUserId());
        if(ObjectUtil.isNotEmpty(pageReqVO.getApartmentId()) && pageReqVO.getApartmentId().equals(0L)){
            wrapper.isNull(MemberFeedback::getApartmentId);
        } else if (ObjectUtil.isNotEmpty(pageReqVO.getApartmentId())) {
            wrapper.eq(MemberFeedback::getApartmentId, pageReqVO.getApartmentId());
        }        wrapper.and(ObjectUtil.isNotEmpty(pageReqVO.getSearchBox()), w -> {
            w.like(MemberFeedback::getUserName, "%" + pageReqVO.getSearchBox() + "%")
                    .or()
                    .like(MemberFeedback::getMobile, "%" + pageReqVO.getSearchBox() + "%")
                    .or()
                    .like(MemberFeedback::getFeedback, "%" + pageReqVO.getSearchBox() + "%");
        });
        wrapper.orderByAsc(MemberFeedback::getStatus);
        wrapper.orderByDesc(MemberFeedback::getCreateTime);
        List<MemberFeedback> memberFeedbacks = memberFeedbackMapper.selectList(wrapper);
        return MemberFeedbackConvert.INSTANCE.convertList(memberFeedbacks);
    }

    @Override
    public Long incompleteNum() {
        LambdaQueryWrapper<MemberFeedback> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(MemberFeedback::getStatus, FeedbackStatusEnum.UNPROCESSED.getCode());
        return memberFeedbackMapper.selectCount(wrapper);
    }

    private MemberFeedback checkAndGet(Long id){
        MemberFeedback memberFeedback = memberFeedbackMapper.selectById(id);
        if(ObjectUtil.isEmpty(memberFeedback)){
            throw new ServiceException(FEEDBACK_EXIST_ERROR);
        }
        return memberFeedback;
    }

}
